package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

/*
const (
    // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
    O_RDONLY int = syscall.O_RDONLY // open the file read-only.
    O_WRONLY int = syscall.O_WRONLY // open the file write-only.
    O_RDWR   int = syscall.O_RDWR   // open the file read-write.
    // The remaining values may be or'ed in to control behavior.
    O_APPEND int = syscall.O_APPEND // append data to the file when writing.
    O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
    O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.
    O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
    O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
)
*/

func ReadMode(name string) {
	// os.O_RDONLY: 只读模式, 文件存在则返回文件指针; 文件不存在则报错
	file, err := os.OpenFile(name, os.O_RDONLY, 666)
	if err != nil {
		fmt.Println(err)
	}
	reader := bufio.NewReader(file)
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		fmt.Println(string(line))
	}
}

func TruncMode(name string) {
	// os.O_TRUNC: 清空模式, 文件存在则清空文件的内容; 文件不存在则报错
	_, err := os.OpenFile(name, os.O_TRUNC, 666)
	if err != nil {
		fmt.Println(err)
	}
}

func CreateMode(name string) {
	// os.O_CREATE: 创建模式, 文件不存在则创建新文件; 存在也不报错
	file, err := os.OpenFile(name, os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(file)
}

func AppendMode(name string) {
	// os.O_APPEND: 追加模式, 配合写操作一起, 在文件末尾追加新的内容
	// 如果没有写操作, 往文件里写数据, 则不会报错也不能写进去任何东西
	file, err := os.OpenFile(name, os.O_APPEND, 0666)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(file)
}

func writeBuffer0(filename string) {
	// 打开一个新文件, 写入3句:golang
	// os.O_WRONLY: 代表写入文件
	// os.O_CREATE: 代表创建文件, 如果文件不存在则创建, 推荐在写入文件的时候加上
	// 如果文件不存在, 直接os.O_WRONLY会报错
	file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0755)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	str := "golang"
	writer := bufio.NewWriter(file)
	for i := 0; i < 3; i++ {
		writer.WriteString(str + "\n")
	}
	// 因为writer是带缓存, 所以WriteString是写入到了缓存, 所以需调用Flush, 将缓存写入到文件
	writer.Flush()
}

func writeBuffer1(filename string) {
	// 打开一个存在的文件, 将原来的数据覆盖为新的3句: 你好中国, 并将文件权限设置为666
	file, err := os.OpenFile(filename, os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	str := "你好中国"
	writer := bufio.NewWriter(file)
	for i := 0; i < 3; i++ {
		_, _ = writer.WriteString(str + "\n")
	}
	_ = writer.Flush()
}

func writeBuffer2(filename string) {
	// 打开一个存在到文件, 在原文件末尾追加3句: 北京~
	file, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND, 0755)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	str := "北京~"
	writer := bufio.NewWriter(file)
	for i := 0; i < 3; i++ {
		writer.WriteString(str + "\n")
	}
	writer.Flush()
}

func writeBuffer3(filename string) {
	// 打开一个文件读取内容, 然后再追加五句: 好饿啊~
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND, 0755)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	for {
		str, err1 := reader.ReadString('\n')
		if err1 == io.EOF {
			break
		}
		fmt.Print(str)
	}
	str := "好饿啊~\r\n"
	writer := bufio.NewWriter(file)
	for i := 0; i < 5; i++ {
		writer.WriteString(str)
	}
	writer.Flush()
}

func writeAll1(filename1, filename2 string) {
	// 读取一个文件的内容并写入到另一个文件
	file1, err1 := ioutil.ReadFile(filename1)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	err2 := ioutil.WriteFile(filename2, file1, 0755)
	if err2 != nil {
		fmt.Println(err2)
	}
}

func FileExists(filename string) (bool, error) {
	/*
		判断文件或文件夹是否存在

		用os.Stat()返回的错误值进行判断
		• 如果返回值是nil, 说明文件或文件夹存在
		• 如果返回的错误使用os.IsNotExist()判断为true, 说明文件或文件夹不存在
		• 如果返回的错误为其他类型, 则不确定是否存在
	*/
	_, err := os.Stat(filename)
	exist := false
	if err == nil {
		fmt.Printf("%s存在\n", filename)
		exist = true
	} else if os.IsNotExist(err) {
		fmt.Printf("%s不存在\n", filename)
	} else {
		fmt.Printf("无法确定%s是否存在\n", filename)
	}
	return exist, err
}

func CopyFile(source, dst string) (written int64, err error) {
	// 将一个文件拷贝到别的目录
	file, err := os.Open(source)
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()
	reader := bufio.NewReader(file)

	dstFile, err1 := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, 0666)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	defer dstFile.Close()
	writer := bufio.NewWriter(dstFile)
	return io.Copy(writer, reader)
}

func main() {
	//ReadMode("0.xtx")
	//CreateMode("0.txt")
	//TruncMode("0.txt")
	//writeBuffer0("0.txt")
	//writeBuffer1("0.txt")
	AppendMode("0.txt")
}
